home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d1
/
movbasv4.arc
/
MOVBASIC.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-11-29
|
19KB
|
520 lines
Title MOVBASIC 3-3-86 [9-17-86]
Page 80,132
;This program must be run on an IBM-PC or IBM-PC/at with ROMS installed
;BASIC.COM and BASICA.COM must reside in same directory as MOVBASIC.
;
;The program takes IBM basic.com or basica.com and combines it with the
;rom image to create a new file called SBASIC.COM or SBASICA.COM, and
;it now works with files above 32k such as PC-DOS 3.2 file BASICA.COM
;
;These new programs can be run on clones with out the copyrighted IBM
;basic ROMS, and will act as if they were running on a true IBM-PC
;
;Works great, type MOVBASIC and follow the prompts...
;
;To generate the executable MOVBASIC.COM file, please type
;
; MASM MOVBASIC;
; LINK MOVBASIC;
; EXE2BIN MOVBASIC MOVBASIC.COM;
;
lf equ 0Ah ; Ascii carriage return
cr equ 0Dh ; Ascii line feed
;
fcb equ 5Ch ; Address of FCB in PSP
fixmax equ 50h ; Maximum number of fixups
;
prog segment
assume cs:prog ,ds:prog, es:prog ,ss:prog
org 0100h
;
main proc near ;Main procedure
mov sp,offset main ; ..use local stack
call copy ; ..read ROM
call rfile ; ..read BASICx.COM
call fixup ; ..scan BASICx.COM for Fixups
call sizit ; ..find size, save in HDR
call chksum ; ..save chksum in HDR
call wfile ; ..write Fixups+ROM+BASICx.COM
int 20h ; ..all done, back to DOS
main endp ; ..end of main procedure
;
subttl copy - procedure to make copy of hardware 'ROM' basic
copy proc near ; Makes copy of ROM
xor ax,ax ; ...get bios data
mov ds,ax ; ...area in ds seg
mov bx,60h ; ...BX --> basic in 'ROM's
mov ax,[bx+0] ; Check ibm ROM vector offset
or ax,ax ; ...offset must be zero
jnz badrom ; ...else no IBM roms
mov ax,[bx+2] ; Check ibm ROM vector segment
cmp ax,0F600h ; ...must begin at F600
jnz badrom ; ...else no IBM roms
mov ds,ax ; AX --> IBM rom segment
mov cx,8000h ; CX == size of ROM basic
mov di,offset ibmbas ; DI --> Private 'ROM' offset
mov si,0 ; SI --> IBM 'ROM' offset
cld ; ...direction forwards
repz movsb ; Copy IBM rom into 'ROM' area
push cs ; ...then restore
pop ds ; ...data segment
ret ; All done, back to caller
;
badrom: push cs ; Restore the
pop ds ; ...data segment
mov dx,offset rommsg ; DX --> error message
jmp near ptr errxit ; ...print and expire
copy endp ; End of copy procedure
;
rommsg db cr,lf
db 'Please run this program on an IBM computer with'
db ' the basic ROMS installed',cr,lf,7,'$'
;
subttl rfile - procedure to read contents of original ibm BASICx.COM file
rfile proc near ; Procedure reads BASICx.COM
mov al,byte ptr ds:fcb+01h ; AL = First char of filename
cmp al,20h ;' ' ; ...was filename specified
jz menu ; ...no, then prompt for it
mov al,byte ptr ds:fcb+10h ; Was a disk number specified?
cmp al,0Fh ; ...valid only up to 0Fh
jb disk ; Else force default disk
xor al,al ; ...by zeroing disk number
;
disk: mov ofile,al ; Save disk number in FCB
jmp short try ; ...try to open file
;
menu: call prompt ; Print selection for user
try: mov di,offset fcb+09h ; DI --> extension in FCB
mov ax,04F43h ; AX == 'CO'
cld ; ...clear direction
stosw ; ...save 'CO' in extension
mov al,4Dh ;'M' ; AL == 'M'
stosb ; ...save 'M' in extension
mov cx,1Eh ; CX == byte count for reset
xor al,al ; AL == what to put in bytes
repz stosb ; ...reset remainder of FCB
mov ah,0Fh ; AH == open existing file
mov dx,offset fcb ; DX --> fcb for this file
int 21h ; ...try to open the file
or al,al ;Test the return code from DOS
jz opened ; ...all is ok
mov dx,offset filmsg ; Else DX --> nasty message
mov ah,09h ; ... AX == DOS print request
int 21h ; ... let DOS complain
dec byte ptr tries ; One less retry (began with 2)
jnz menu ; ... has second chance
int 20h ; Else call the terminator
;
opened: mov word ptr ds:fcb+0Eh,01h ; Records are 1h bytes long
push ds ; Save data segment
mov ah,1Ah ; AH == set disk xfer address
mov bx,ds ; Get current segment
add bx,800h ; ...point beyond ROMs
mov ds,bx ; Load into DS segment
mov dx,offset ibmbas ; ...xfer address = 'ROM'end
int 21h ; ...tell DOS to set address
pop ds ; Restore data segment
mov ah,27h ; Attempt to read entire file
mov cx,offset 0FFFFh ; ...only up to 64k bytes
mov dx,offset fcb ; ...with this FCB
int 21h ; ...into disk xfer address
cmp al,01h ; Must return end_of_file
jnz huge ; ...else file is oversize
cmp ds:ibmbas+8000h,5A4Dh ; Is file a COM file?
je exefil ; ...no, can't move it
mov word ptr ds:ifsize,cx ; Save size in 1h byte blocks
ret ; ...all done read, return
;
huge: jmp near ptr toobig ; ...else can't convert
exefil: jmp near ptr notcom ; ...not a COM file
rfile endp ; End of read file procedure
;
subttl prompt - procedure to get filename from user
prompt proc near ; Prompt for BASICx file name
mov dx,offset banner ; DX --> display
mov ah,09h ; AH == print string
int 21h ; ...ask DOS to print prompt
mov ah,01h ; Read reply from console
int 21h ; ...this DOS request
sub al,31h ; Was it choice #1?
jz newnam ; ...yup
cmp al,01h ; Was it choice #2?
jnz prompt ; ...nope, must be 1 or 2
mov byte ptr ifpat,41h ;'A' ; Add 'A' to end of filename
;
newnam: mov si,offset ifile ; Pack explicit name
mov di,offset fcb ; ...into input FCB
mov cx,0Ch ; ...length of name
cld ; Clear direction flag
repz movsb ; ...copy name there
mov cx,18h ; ...reset input FCB
xor al,al ; ...write zero to it
repz stosb ; ...with instruction
ret ; Back to caller
prompt endp ; ...end of procedure
;
tries db 2 ; Attempts before we give up
;
banner db cr,lf,lf
db ' BASIC Relocation Utility Version 3.01'
db cr,lf,lf,lf
db 'This program will convert BASIC.COM or BASICA.COM into'
db ' SBASIC[A].COM which is',cr,lf
db 'usable on CLONE COMPUTERs that do not have IBM`s patented '
db 'BASIC ROMs installed',cr,lf,lf
db 'If you have BASIC[A].COM on non-default drive',2Ch
db 'then specify that in the command ',cr,lf
db 'line. For ex. MOVBASIC A:BASIC B: will create SBASIC.'
db 'COM on the B: drive. ',cr,lf,lf
db 'Select BASIC to patch for CLONE (non-IBM) computer'
db cr,lf,lf
db ' 1. BASIC.COM --> SBASIC.COM',cr,lf
db ' 2. BASICA.COM --> SBASICA.COM',cr,lf
db ' --> $'
;
filmsg db cr,lf,'Cannot find specified file. Please retry.',7,'$'
;
ifile db 0 ; Disk number
db 'BASIC' ; ...filename
ifpat db ' ' ; ...possibly 'A'
db 'COM' ; ...extension
;
subttl fixup - procedure to build table of fixup offsets
fixup proc near ; Revector ROM references
mov bx,offset ibmbas ; BX => BASICx.COM in memory
mov cx,word ptr ds:ifsize ; CX == Size in 1h byte blocks
mov dx,0F600h ; DX == hardware (ROM) address
push ds ; Save data segment
mov ax,ds ; Get data segment
add ax,800h ; ...move beyond ROMs
mov ds,ax ; Load into data segment
mov di,offset fixups ; DI -> start of fixup table
cld ; ...clear direction flag
;
fixing: cmp dx,[bx] ; BASICx.COM want ROM segment?
jnz next ; ...no, do not alter
call lookup ; Should seg. ref. be fixed up?
jnz next ; ...flag 'Z' clear if no
mov ax,bx ; Get address that needs fixup
sub ax,offset ibmbas ; ...find BASICx.COM offset
stosw ; Store offset in fixups table
inc word ptr cs:nfixes ; ...one more offset in table
next: inc bx ; Scan the next byte
loop fixing ; ...until done BASICx.COM
pop ds ; Restore Data segment
cmp word ptr ds:nfixes,fixmax ; Did fixup table overflow?
ja loaded ; ...jump if so
ret ; Else end of fixup procedure
;
loaded: jmp near ptr tooful ; Fixup table overloaded
;
fixup endp ; ...show end
subttl lookup - find if offset into BASICx.COM needs fixup
;
; Lookup - procedure sets 'Z' flag if this F600h reference needs a fixup
;
lookup proc near ; See if reference needs fixup
cmp byte ptr [bx-3],0EAh
jz found
cmp byte ptr [bx-1],0B8h
jz found
cmp byte ptr [bx-1],0BBh
jz found
cmp byte ptr [bx-1],0BEh
jz found
cmp byte ptr [bx-1],0BAh
jz found
cmp byte ptr [bx-1],0BFh
jz found
cmp byte ptr [bx-1],0B9h
jz found
cmp byte ptr [bx-3],09Ah
jz found
cmp word ptr [bx-4],06C7h
jz found
cmp word ptr [bx-4],87C7h
jz found
cmp word ptr [bx-4],84C7h
jz found
cmp word ptr [bx-4],85C7h
jz found
cmp word ptr [bx-4],86C7h
jz found
cmp word ptr [bx-3],46C7h
jz found
cmp word ptr [bx-3],47C7h
jz found
cmp word ptr [bx-3],44C7h
jz found
cmp word ptr [bx-3],45C7h
jz found
cmp word ptr [bx-2],07C7h
jz found
cmp word ptr [bx-2],04C7h
jz found
cmp word ptr [bx-2],05C7h
found: ret ; Return, result in Z flag
lookup endp ; ...end of procedure
;
subttl sizit - procedure to find size of SBASIC.COM and save in HDR
sizit proc near
mov ax,offset ibmbas-hdr ; Get header size into AX
add ax,8000h ; ...add size of ROM set
add ax,word ptr ifsize ; ...and input file size
push ax ; Save copy of file size
mov cl,09h ; ...find number of blocks
rcr ax,cl ; ...by 9 bit right shift
and ax,0FFh ; ...0FFh blocks maximum
inc ax ; I dunno, but DOS wants it
mov word ptr hdr+04h,ax ; Save number of blocks in hdr
pop ax ; ...get low order 16 bits
and ax,01FFh ; Isolate the block fraction
mov word ptr hdr+02h,ax ; ...and save in hdr word
ret ; ...return to caller
sizit endp
;
subttl chksum - procedure to calculate and store negative checksum of file
chksum proc near
xor ax,ax ; Prepare a zero
mov dx,word ptr hdr+04h ; Load block count
chks01: mov si,offset movrom ; si --> blk start
dec dx ; ...show one less
js chks03 ; Negative if done
mov cx,0100h ; ...words in block
chks02: sub ax,[si] ; Subtract word
add si,02h ; ...point to next
loop chks02 ; ...go until done
mov bx,ds ; ...get a copy
add bx,0020h ; ...Go to next blk
mov ds,bx ; ...and save in ds
jmp chks01 ; ...back for next
chks03: mov cx,offset hdr+02h ; Get fraction blk
shr cx,01h ; ...into words
jcxz chks05 ; Zero if all done
chks04: sub ax,[si] ; Subtract word
add si,02h ; ...point to next
loop chks04 ; ...go until done
chks05: push cs ; Get code segment
pop ds ; ...restore ds
mov word ptr hdr+12h,ax ; Negative chksum
ret ; ...return caller
chksum endp
;
subttl wfile - procedure to write new SBASICx.COM file
wfile proc near ; Procedure writes BASICx.COM
mov al,byte ptr ds:fcb+06h ; Last character of filename
cmp al,41h ; ...does it end in 'A'?
jnz around ; ...no, leave it alone
mov ofpat,al ; ...else copy 'A'
around: mov ah,16h ; Create output file
mov dx,offset ofile ; ...with (patched) FCB
int 21h ; ...with system call
or al,al ; Did the create work?
jnz dskcre ; ...say disk is full
mov word ptr orecl,01h ; Records are 1 byte long
mov cx,offset ibmbas-hdr ; ...overhead in bytes
add cx,8000h ; ...rom size in bytes
jc toobig ; Out of memory, complain(?!)
mov ah,1Ah ; Set disk transfer address
mov dx,offset hdr ; ...to our start-up code
int 21h ; ...with this call
mov dx,offset ofile ; DX --> Output FCB
mov ah,28h ; ...write patched file
int 21h ; ...with system call
or al,al ; Did the write succeed?
jnz dskful ; ...no, say disk is full
mov word ptr orecn,cx ; Point to next record
push ds ; ...save a copy
mov ax,ds ; Get data segment
add ax,800h ; ...go beyond roms
mov ds,ax ; ...reload new segment
mov ah,1Ah ; Set disk transfer address
mov dx,offset ibmbas ; ...where to set it to
int 21h ; Set disk transfer address
pop ds ; ...restore old segment
mov ah,28h ; Write unpatched BASICx.COM
mov cx,word ptr ifsize ; ...input file (bytes)
mov dx,offset ofile ; Write more stuff out
int 21h ; ...with this call
or al,al ; Did the write succeed?
jnz dskful ; ...no, say disk is full
mov ah,10h ; Worked, then close file
mov dx,offset ofile ; DX --> output FCB
int 21h ; Issue the dos call
or al,al ; ...did it close?
jnz dskful ; No, complain
ret ; ...else back to caller
;
tooful: mov dx,offset fulmsg ; Fixup table overflowed
jmp short errxit ; ...on terminal
;
toobig: mov dx,offset bigmsg ;Complain, file is too big
jmp short errxit ; ...jump to print message
;
notcom: mov dx,offset commsg ;Not a COM file, complain
jmp short errxit ; ...jump to print message
;
dskcre: mov dx,offset cremsg ;Complain about open error
jmp short errxit ; ...jump to print message
;
dskful: mov dx,offset dskmsg ;Complain about disk full
;
errxit: mov ah,09h ; Function = print message
int 21h ; ...ask DOS to type it
int 20h ; Then call the terminator
wfile endp ; ...end write file procedure
;
; *** Start of real FCB structure for output file
;
ofile db 0 ; Disk number
db 'SBASIC' ; ...filename
ofpat db ' ' ; ...possibly 'A'
db ' COM' ; ...extension
dw 0 ; Current record in FCB
orecl dw 0 ; Output record size
db 11h dup(0) ; ...rest of FCB
orecn dw 0,0 ; Output record number
;
; *** End of real FCB structure for output file
;
bigmsg db cr,lf
db 'Your BASIC file is too big',cr,lf,7,'$'
commsg db cr,lf
db 'Not COM file',cr,lf,7,'$'
cremsg db cr,lf
db 'Can',27h,'t create SBASIC',cr,lf,7,'$'
dskmsg db cr,lf
db 'Output disk full',cr,lf,7,'$'
fulmsg db cr,lf
db 'Too many fixups',cr,lf,7,'$'
;
subttl hdr - everything beyond here added to SBASICx.COM image file
;
extra equ 27FFh ; Minimum paragraphs to run
;
hdr label byte ; Header for SBASICs.COM
db 4Dh,5Ah ; ...image .EXE type
dw ? ; Fraction of block
dw ? ; Blocks in image
dw 0h ; Number of relocations
dw (0Fh+base-hdr)/10h ; Header size in paragraphs
dw (0Fh+fixups-ipl)/10h+extra ; Minimum paragraphs to run
dw 0FFFFh ; Maximum paragraphs to run
dw 0h ; Offset for SS register
dw tos-base ; ...value SP register
dw ? ; Negative checksum
dw 0h ; Offset for IP register
dw 0h ; ...value CS register
dw ? ; Byte disp of reloc. list
dw 0 ; ...not an overlay
;
dw 2 dup(?) ; Align on paragraph boundary
;
subttl img - everything beyond here will apear in memory when image is loaded
;
; Everything below this line will appear in the output SBASICx.COM image, and
; will appear in memory when this image is loaded. Memory offsets as follows
;
; 0000h == Start of PSP (Program Segment Prefix - not part of image )
;base: 0100h == Symbol GO (Setup COM environment in CS,DS and go there)
; 0111h == Symbol MOVROM (check memory, copy basic ROM to high memory)
; 0139h == Symbol RUNFIX (apply fixups to original BASICx.COM image )
; 0152h == Symbol MOVIPL (moves IPL code to stack area for execution )
; 0169h == Symbol IPL (moves ibm BASICx.COM to 0100h and starts it)
; 0192h == Symbol FIXUPS (list of offsets into BASICx.COM for fixups )
; 0232h == Symbol IBMBAS (copy of ibm basic ROM set, without patches)
; 8232h == (original ibm BASICx.COM without fixups done)
;end: ????h == (end BASICx.COM May not exceed 96k in total)
;
base label byte ; At run-time appears at 0100h
;
go proc far ; Setup regs like COM file
cli ; No interrupts for now !!!
mov ax,cs ; ...get code segment
sub ax,10h ; ...then point to PSP
mov ds,ax ; ...load into Data Segment
mov ds:(100h+goseg-base),ax ; ...save copy for CS
db 0EAh ; Jump far
gooff dw 100h+movrom-base ; ...offset for IP
goseg dw ? ; ...segment for CS
go endp
;
dw ? ; Bootstrap word for stack
tos label word ; Procedure GO becomes stack
;
movrom proc near ; Routine relocates ROM up hi
mov si,offset ibmbas+100h-base ; SI -> where 'ROM's live now
mov di,0 ; DI -> where 'ROM's will be
mov ax,cs ; Get our code segment
add ax,extra-8FFh ; + minimum memory required
xor al,al ; ...round down to even 4K
push ax ; Run-time segment for ROM set
mov es,ax ; ...load into es for movsb
mov cx,8000h ; Bytes in basic 'ROM' set
cld ; ...clear the direction
repz movsb ; Move ROMs from BASIC data area
mov di,si ; DI -> where BASICx.COM is now
xor ax,ax ; Prepare es segment to
mov es,ax ; ...access vector area
mov bx,60h ; BX --> Basic vector into ROM
pop dx ; DX --> run-time 'ROM' segment
mov es:[bx+2],dx ; ...save 'ROM' seg. in vector
mov es:[bx+0],ax ; ...the 'ROM' offset is zero
movrom endp ; End of copy_rom procedure
;
runfix proc near ; Routine does runtime fixups
mov cx,0000h ; CX == number of fixups
nfixes =$ - 02h ; ...self-modifying code, ugh!
mov si,offset fixups+100h-base ; SI -> fixup table
mov ax,ds ; Get data segment
add ax,800h ; ...go beyond ROMs
mov es,ax ; ...and save it
sub di,8000h ; do this to avoid
fixer: lodsw ; AX == offset into BASICx.COM
mov bx,ax ; copy offset into BX
mov es:[bx+di],dx ; Fixup ROM ref. in BASICx.COM
loop fixer ; ..loop until all fixups done
runfix endp ; End of run-time fixup routine
;
movipl proc far ; Move IPL code to scratch area
mov ax,cs ; Get code segment
add ax,offset extra-9FFh ; ...find scratch area
xor al,al ; ...even boundary
push ax ; Save scratch segment
pop es ; ...load into ES reg.
push ax ; Save scratch segment
mov di,0h ; DI -> where IPL code will run
push di ; Save offset to IPL code
mov si,offset ipl+100h-base ; SI -> where IPL code is now
mov cx,offset fixups-ipl ; CX == size of IPL code, bytes
repz movsb ; ...copy IPL code to ipl area
ret ; ...start final IPL sequence
movipl endp ; End of IPL relocate procedure
;
ipl proc far ; IPL code runs in high memory
mov cx,0000h ; CX == size of BASICx.COM file
ifsize =$ - 02h ; ...self-modifying code, ugh!
mov ax,ds ; Save code segment copy
mov es,ax ; ...load into extra seg
mov word ptr cs:(iplseg-ipl),ax ; Save code segment for ipl
add ax,800h ; ...skip over 32K roms
mov ds,ax ; DS register --> ROM now
mov si,offset ibmbas+100h-base ; SI -> area BASICx.COM is now
mov di,100h ; DI -> area BASICx.COM must go
repz movsb ; Copy BASICx.COM to low memory
mov ax,es ; Restore data segment
mov ds,ax ; ...equal to extra seg
mov ss,ax ; Set stack seg for COM
mov sp,0FFFEh ; ...stack reg for COM
sti ; ...interrupts now safe
db 0EAh ; JMP FAR segment:offset
iploff dw 100h ; ...offset for COM file
iplseg dw ? ; ...Start seg COM file
ipl endp ; ..end of IPL procedure
;
fixups label word ; Fixups as offset in BASIC.COM
ibmbas equ fixups + (2 * fixmax) ; Contents of 'ROM's saved here
prog ends
;
end main